package com.carpedil.shirodemo.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.carpedil.shirodemo.common.exception.BizRuntimeException;
import com.carpedil.shirodemo.common.util.ShiroUtil;
import com.carpedil.shirodemo.common.util.TreeUtil;
import com.carpedil.shirodemo.system.mapper.MenuMapper;
import com.carpedil.shirodemo.system.model.Menu;
import com.carpedil.shirodemo.system.model.User;
import com.carpedil.shirodemo.system.service.IMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * 服务实现类
 *
 * @author carpedil
 * @since 2021-01-05
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {

  @Autowired private MenuMapper menuMapper;

  /** 获取当前登陆用户拥有的树形菜单 (admin 账户拥有所有权限.) */
  @Override
  public List<Menu> selectCurrentUserMenuTree() {
    // 从shiro中取出当前登录用户
    User currentUser = ShiroUtil.getCurrentUser();

    return selectMenuTreeByUsername(currentUser.getUsername());
  }

  /**
   * 根据用户名获取该用户拥有的树形菜单
   *
   * @param username 用户名
   * @return 封装好的树状层级关系的Menu集合
   */
  @Override
  public List<Menu> selectMenuTreeByUsername(String username) {
    List<Menu> menus = null;

    if ("admin".equals(username)) {
      menus = menuMapper.selectList(new QueryWrapper<Menu>().orderByAsc("order_num"));
    } else {
      menus = menuMapper.selectMenuByUserName(username);
    }

    return toTree(menus);
  }

  /** 将普通的Menu集合转换为树形结构 */
  private List<Menu> toTree(List<Menu> menuList) {
    return TreeUtil.toTree(menuList, "menuId", "parentId", "children", Menu.class);
  }

  /**
   * 查询所有的menu，并组装层级关系(数据库直接子查询获取)
   *
   * @return 有树状层级关系的Menu集合
   */
  @Override
  public List<Menu> selectAllTree() {
    return menuMapper.selectAllTree();
  }

  @Override
  public List<Menu> getLeafNodeMenu() {
    List<Menu> menus = selectAllTree();
    return TreeUtil.getAllLeafNode(menus);
  }

  @Override
  public List<Menu> getAllMenuTreeAndRoot() {
    List<Menu> menus = this.selectAllTree();
    return addRootNode("导航目录", 0, menus);
  }

  @Override
  public List<Menu> getRootMenuChildList(Integer parentId) {
    return menuMapper.selectByParentId(parentId);
  }

  @Override
  public void swapSortOrder(Integer currentId, Integer swapId) {
    menuMapper.swapOrder(currentId, swapId);
  }

  @Override
  public boolean insertMenu(Menu menu) {
    Integer orderNum = menuMapper.selectMaxOrderNum();
    menu.setOrderNum(orderNum + 1);
    return this.save(menu);
  }

  @Override
  @Transactional(rollbackFor = BizRuntimeException.class)
  public void deleteMenuById(Integer menuId) {
    List<Menu> menus = menuMapper.selectByParentId(menuId);
    if (menus.size() > 0) {
      throw new BizRuntimeException("一级菜单包含子菜单,不能删除");
    } else {
      menuMapper.deleteById(menuId);
    }
  }

  @Override
  public List<Menu> getAllMenuAndCountOperatorTreeAndRoot() {
    List<Menu> menus = menuMapper.selectAllMenuAndCountOperator();
    return addRootNode("导航目录", 0, menus);
  }

  private List<Menu> addRootNode(String rootName, Integer rootId, List<Menu> menus) {
    Menu root = new Menu();
    root.setMenuId(rootId);
    root.setMenuName(rootName);
    root.setChildren(menus);
    List<Menu> rootList = new ArrayList<>();
    rootList.add(root);
    return rootList;
  }
}
